package com.lagou.niancheng.rpc.server.spring;

import com.lagou.niancheng.rpc.common.converter.Converter;
import com.lagou.niancheng.rpc.common.exceptions.SimpleRpcException;
import com.lagou.niancheng.rpc.server.SimpleRpcConfig;
import com.lagou.niancheng.rpc.server.SimpleRpcServerProvider;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

import java.util.Map;

/**
 * 服务提供者注册器
 * 该注册器会注入serviceProvider的扫描器
 *
 * @author 大犬
 * @date 2020/5/1
 */
public class ServiceProviderFactoryRegistrar implements ImportBeanDefinitionRegistrar {

    private static final String SIMPLE_RPC_SERVICE_PROVIDER_SCANNER = ServiceProviderScanner.class.getName();

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // 1.获取配置
        SimpleRpcConfig simpleRpcConfig = buildConfig(importingClassMetadata);
        // 2.创建SimpleRpc服务注册中心,这一步中同时会启动rpc服务
        SimpleRpcServerProvider simpleRpcServerProvider = new SimpleRpcServerProvider(simpleRpcConfig);
        // 3.将serviceProviderScanner注册到容器中
        registrarServiceProviderScanner(simpleRpcServerProvider, registry);
    }

    private void registrarServiceProviderScanner(SimpleRpcServerProvider simpleRpcServerProvider, BeanDefinitionRegistry registry) {
        RootBeanDefinition providerScannerBeanDefinition = new RootBeanDefinition(ServiceProviderScanner.class);
        ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
        constructorArgumentValues.addIndexedArgumentValue(0, simpleRpcServerProvider);
        providerScannerBeanDefinition.setConstructorArgumentValues(constructorArgumentValues);
        registry.registerBeanDefinition(SIMPLE_RPC_SERVICE_PROVIDER_SCANNER, providerScannerBeanDefinition);
    }

    @SuppressWarnings("unchecked")
    private SimpleRpcConfig buildConfig(AnnotationMetadata importingClassMetadata) {
        Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(EnableSimpleRpc.class.getName());
        SimpleRpcConfig simpleRpcConfig = new SimpleRpcConfig();
        if (annotationAttributes == null) {
            return simpleRpcConfig;
        }
        int port = (int) annotationAttributes.get("port");
        int workerThreadPoolSize = (int) annotationAttributes.get("workerThreadPoolSize");
        int masterThreadPoolSize = (int) annotationAttributes.get("masterThreadPoolSize");
        Class<? extends Converter> converterClass = (Class<? extends Converter>) annotationAttributes.get("converterClass");
        Converter converter;
        try {
            converter = converterClass.newInstance();
        } catch (Exception e) {
            throw new SimpleRpcException("instant converter failed", e);
        }
        simpleRpcConfig.setPort(port);
        simpleRpcConfig.setMasterThreadPoolSize(masterThreadPoolSize);
        simpleRpcConfig.setWorkerThreadPoolSize(workerThreadPoolSize);
        simpleRpcConfig.setConverter(converter);
        return simpleRpcConfig;
    }
}
